/****************************************************************************/
/*
* create the share memory file on host pc, auto run after compile.
*/
/****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

#include "libmdm.h"
#include "xml_parse_lib.h"

#include "cms_common.h"
#include "cms_mdm.h"
#include "cms_log.h"
#include "cms_xmlToShm.h"



static cmsoffset_t current_offset = 0;	/*current offset from beginning of share memory*/
static uint32_t total_size = 0;			/*total size of share memory size*/
static int totalOIDNumber = 0;			/*== OID number*/
cmsXmlCb_t XmlContrlBlock;
cmsXmlCb_t	*xmlShmCb = &XmlContrlBlock;
//functionList_t *functionQueue = NULL;


const char *OBJID_FILE_HEADER = "\
#include \"cms_common.h\"\n\
\n\
typedef struct OIDArray\n\
{\n\
	int OID;\n\
	cmsoffset_t offset;\n\
	char fullpath[256];\n\
	int writable;\n\
} OIDArray_t;\n\
\n\
";

const char *OBJID_TABLE_HEADER = "\
#include \"cmsXml_obj_id.h\"\n\
\n\
OIDArray_t OIDTable[] = {\
";

const char *OBJID_FILE_TAIL = "\
,\n/* Final */\n\t{\t0,\t0,\t\"\"\t}\
\n};\n\
";

const char *TABLE_FILE_TAIL = "\
/* Final */\t{ NULL, 0}\
\n};\n\
";

char OBJ_MAXCOUNT[180*200] = "\
\n\
typedef struct\n\
{\n\
	char objBuf[180];\n\
	int count;\n\
} ObjMaxCountArray_t;\n\
\n\
ObjMaxCountArray_t ObjCountTable[] = {\
\n\
";

const char *OBJ_MAXCOUNT_TAIL = "\
\t{	\"\",	0}\
\n};\n\
";
//OIDTable

static int cmsXml_NodeCopyObject(objectNode_t *src, objectNode_t *dst);
//static cmsoffset_t cmsXml_CopyNode(objectNode_t *src, parentList_t *pList);
static int cmsXml_regParameter(objectNode_t *node, char *buf);
static void cmsWriteRoutinehfile(char *pre_str, char *file, char *objName);
static void cmsWriteRoutinetablefile(char *pre_str, char *file, char *objName, int OID, uint32_t priority);
//static void cmsWriteRoutineCfile(char *pre_str, char *file, char *objName);


uint32_t getRdmTotalSize( void )
{
	return total_size;
}

void addRdmTotalSize( uint32_t size )
{
	total_size += size;
}

static void rep(char *s,char *s1,char *s2)
{
  char *p;
  for(;*s;s++) 
  {
	for(p=s1;*p&&*p!=*s;p++);
	
	if(*p){
	*s=*(p-s1+s2);
	}
  }
}

/*
 Description: 
 	write parameter to cmsXml_object.h
 Parameters:
 	node: object node ptr 
 	objbuf: temp buf to write
 return:
 	return CMS_OK
 called by:
 	cmsXml_regObjectId()
*/
static int cmsXml_regParameter(objectNode_t *node, char *objbuf){
	int meta_count = 0;
	void *meta_ptr = NULL;
	int meta_size = 0, pad_size = 0, pad_type = 0;
	uint32_t type_size = 0, type = 0;
	char metabuf[32];
	cmsoffset_t attrOffset;
	void *object = NULL;
	uint32_t attr = 0;

	memset(metabuf, 0, sizeof(metabuf));

	/*write parameters*/
	meta_count = NTOHS(node->meta_count);
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->meta));
	while (meta_count){
		memcpy(&meta_size, meta_ptr, sizeof(uint8_t));

		if (meta_size == PADDING_META_LEN){
			memcpy(&pad_size, (meta_ptr+sizeof(uint8_t)*3), sizeof(uint8_t));
			memcpy(&pad_type, (meta_ptr+sizeof(uint8_t)), sizeof(uint8_t));
			/*padding reserve*/
			strcat(objbuf, "	uint8_t ");
			if (pad_type == 1){
				strcat(objbuf, "configReserve");
			}
			else{
				strcat(objbuf, "nonConfigReserve");
			}
			sprintf(metabuf, "[%d];\n", pad_size);
			strcat(objbuf, metabuf);			
		}
		else{
			/*get type_size*/
			memcpy(&type_size, (meta_ptr+meta_size-sizeof(uint32_t)), sizeof(uint32_t));
			attrOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_size - (sizeof(cmsoffset_t)*1+sizeof(uint32_t)))));
			object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->object));
			attr = NTOHL(*((uint32_t *)(object+attrOffset)));
			type = type_size = NTOHL(type_size);

			if ((type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING
				|| (type_size == PARAMETER_TYPE_DATETIME)){
				/*string*/
				if ( attr & PARAMETER_ATTR_NO_MALLOC )
				{
					strcat( objbuf, "	char *");
					strcat( objbuf, meta_ptr + sizeof( uint8_t ) );
					strcat( objbuf, ";\n");
				}
				else
				{
					strcat( objbuf, "	char " );
					strcat( objbuf, meta_ptr + sizeof( uint8_t ) );
					/*remove the first two bits to get the real parameter size*/
					if ( type_size == PARAMETER_TYPE_DATETIME )
						type_size = PARAMETER_TYPE_DATETIME;
					else
						type_size &= ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
					sprintf( metabuf, "[%d];\n", type_size );
					strcat( objbuf, metabuf );
				}
			}
			else if(type_size  == PARAMETER_TYPE_MAC){
				/*mac*/
				strcat(objbuf, "	uint8_t ");
				strcat(objbuf, meta_ptr+sizeof(uint8_t));
				/*remove the first two bits to get the real parameter size*/
				sprintf(metabuf, "[%d];\n", MAC_LENGTH);
				strcat(objbuf, metabuf);
			}
			else{
				switch(type_size){
				case PARAMETER_TYPE_UINT8:
				case PARAMETER_TYPE_BOOLEAN:
					strcat(objbuf, "	uint8_t ");
					break;
				case PARAMETER_TYPE_UINT16:
					strcat(objbuf, "	uint16_t ");
					break;
				case PARAMETER_TYPE_UINT32:
					strcat(objbuf, "	uint32_t ");
					break;
				case PARAMETER_TYPE_UINT64:
					strcat(objbuf, "	uint64_t ");
					break;
				case PARAMETER_TYPE_SINT7:
					strcat(objbuf, "	int8_t ");
					break;
				case PARAMETER_TYPE_SINT15:
					strcat(objbuf, "	int16_t ");
					break;
				case PARAMETER_TYPE_SINT31:
					strcat(objbuf, "	int32_t ");
					break;
				case PARAMETER_TYPE_SINT63:
					strcat(objbuf, "	int64_t ");
					break;						
				}
				strcat(objbuf, meta_ptr+sizeof(uint8_t));
				strcat(objbuf, ";\n");					
			}
			/*add for default value*/				
			if ((attr & PARAMETER_ATTR_DEFAULTVALUE) == PARAMETER_ATTR_DEFAULTVALUE){
				type_size = type;
				if ((type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING
					|| (type_size == PARAMETER_TYPE_DATETIME)){
					/*string*/
					strcat(objbuf, "	char ");
					strcat(objbuf, meta_ptr+sizeof(uint8_t));
					strcat(objbuf, "_default");
					/*remove the first two bits to get the real parameter size*/
					if(type_size == PARAMETER_TYPE_DATETIME)
						type_size = PARAMETER_TYPE_DATETIME;
					else
						type_size &= ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);					
					sprintf(metabuf, "[%d];\n", type_size);
					strcat(objbuf, metabuf);
				}
				else if(type_size  == PARAMETER_TYPE_MAC){
					/*mac*/
					strcat(objbuf, "	uint8_t ");
					strcat(objbuf, meta_ptr+sizeof(uint8_t));
					strcat(objbuf, "_default");
					/*remove the first two bits to get the real parameter size*/
					sprintf(metabuf, "[%d];\n", MAC_LENGTH);
					strcat(objbuf, metabuf);
				}
				else{
					switch(type_size){
					case PARAMETER_TYPE_UINT8:
					case PARAMETER_TYPE_BOOLEAN:
						strcat(objbuf, "	uint8_t ");
						break;
					case PARAMETER_TYPE_UINT16:
						strcat(objbuf, "	uint16_t ");
						break;
					case PARAMETER_TYPE_UINT32:
						strcat(objbuf, "	uint32_t ");
						break;
					case PARAMETER_TYPE_UINT64:
						strcat(objbuf, "	uint64_t ");
						break;
					case PARAMETER_TYPE_SINT7:
						strcat(objbuf, "	int8_t ");
						break;
					case PARAMETER_TYPE_SINT15:
						strcat(objbuf, "	int16_t ");
						break;
					case PARAMETER_TYPE_SINT31:
						strcat(objbuf, "	int32_t ");
						break;
					case PARAMETER_TYPE_SINT63:
						strcat(objbuf, "	int64_t ");
						break;						
					}
					strcat(objbuf, meta_ptr+sizeof(uint8_t));
					strcat(objbuf, "_default");
					strcat(objbuf, ";\n");					
				}			
			}					

		}
		meta_ptr = meta_ptr + meta_size;
		meta_count--;
	}

	/*write parameter attribute*/
	meta_count = NTOHS(node->meta_count);
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->meta));	
	memcpy(&meta_size, meta_ptr, sizeof(uint8_t));
	char flagName[16] = {0};
	if (meta_size != PADDING_META_LEN){
		strcat(objbuf, "	uint32_t ");
		strcat(objbuf, "parameterAttr");
		sprintf(flagName, "_flags[%d];\n",meta_count);
		strcat(objbuf, flagName);
	}

	while (meta_count){
		memcpy(&meta_size, meta_ptr, sizeof(uint8_t));
		if (meta_size != PADDING_META_LEN){

			/*add for default attr*/
			attrOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_size - (sizeof(cmsoffset_t)*1+sizeof(uint32_t)))));
			object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->object));
			attr = NTOHL(*((uint32_t *)(object+attrOffset)));			
			if ((attr & PARAMETER_ATTR_DEFAULTATTR) == PARAMETER_ATTR_DEFAULTATTR){
				strcat(objbuf, "	uint32_t ");
				strcat(objbuf, meta_ptr+sizeof(uint8_t));
				strcat(objbuf, "_defaultFlags;\n");
			}
		}
		else{
			pad_type = 0;
			memcpy(&pad_type, (meta_ptr+sizeof(uint8_t)), sizeof(uint8_t));
			/*add padding attr for structure correct!*/
			strcat(objbuf, "	uint32_t ");
			if (pad_type == 1){
				strcat(objbuf, "configReserve_flags;\n");
			}
			else{
				strcat(objbuf, "nonConfigReserve_flags;\n");
			}
		}
		meta_ptr = meta_ptr + meta_size;
		meta_count--;
	}
	rep(objbuf, "-", "_");	
	return CMS_OK;
}

/*
 Description: 
 	1. create object id in object id header file (cmsXml_obj_id.h)
 	2. create object structure to cmsXml_object.h
 Parameters:
 	node: object node ptr  
 return:
 	return CMS_OK
*/
int cmsXml_regObjectId(objectNode_t *node, parentList_t *pList)
{
	FILE  *fp;
	int i, size=256;
	parentList_t *pCurPList = NULL;
	objectNode_t *pNode = NULL;
	char *node_nameptr, *parent_nameptr;
	char namebuf[size];
	char id[32];
	char buf[2][size];
	char fullpath[2][size];
	int src=0, dest=0, count=0;
	cmsoffset_t offset = 0;
	/*for _(X)*/
	uint32_t attr = 0;
	char defbuf[1024];
	char tmpbuf[1024];//for cmsXml_object.h
	char *objbuf;
	int indexFlag = 0;	/*if indexFlag == 1, means one of parent is index child and parent's name is not i*/
	struct stat statBuf;
	char cmsDefBuf[ BUFLEN_512 ] = { 0 };
	char cmsObjBuf[ BUFLEN_512 ] = { 0 };
	char cmsObjTmp[BUFLEN_512] = { 0 };

	/*init parameter*/
	stat(SYS_DEF_XML_FILE, &statBuf);
	objbuf = calloc(statBuf.st_size+4096, 1);//4096 is for reserved parameter and structure name ... 
	for(i=0;i<size;i++){
		buf[0][i]=0;
		buf[1][i]=0;
		fullpath[0][i]=0;
		fullpath[1][i]=0;
		namebuf[i]=0;
	}
	memset(defbuf, 0, sizeof(defbuf));
	memset(tmpbuf, 0, sizeof(tmpbuf));

	strcat(namebuf, DEF_STR);
	pCurPList = pList;
 
	/*get current node name&attr, and create first list node with attr, D->C->B->A*/
	node_nameptr=cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->name));
	strcpy(buf[src], node_nameptr);
	strcpy(fullpath[src], node_nameptr);

	/*get cur node full path name, and link parent node to list*/
	while(pCurPList!=NULL){
		src=count%2;
		dest=(count+1)%2;
		pNode=pCurPList->node;
		parent_nameptr=cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(pNode->name));
		attr = NTOHL(pNode->attributes);	
		if (((attr & ATTR_INDEXCHILD) == ATTR_INDEXCHILD)&&(*parent_nameptr != 'i')){
			indexFlag = 1;
		}		
		strcpy(buf[dest], parent_nameptr);
		strcat(buf[dest], "_");
		strcat(buf[dest], buf[src]);
		memset(buf[src], 0, sizeof(char) * size);
		strcpy(fullpath[dest], parent_nameptr);
		strcat(fullpath[dest], ".");
		strcat(fullpath[dest], fullpath[src]);
		memset(fullpath[src], 0, sizeof(char) * size);
		count++;

		pCurPList=pCurPList->next;
	}

	/*get parent node name*/
	attr = NTOHL( node->attributes );
	if ((indexFlag == 0) && ((attr & ATTR_OBJECTNODE) == ATTR_OBJECTNODE)){
		/*add object structure to cmsXml_object.h*/
		if (((attr & ATTR_INDEXCHILD) != ATTR_INDEXCHILD) || (*node_nameptr == 'i')){
			memset(defbuf, 0, sizeof(defbuf));

			strcat(objbuf, "typedef struct cmsObj_");
			/*to avoid object node has same name, use the full path name for structure*/
			strcat(tmpbuf, node_nameptr);

			pCurPList = pList;
			while(pCurPList != NULL){
				memset(defbuf, 0, sizeof(defbuf));

				pNode=pCurPList->node;
				parent_nameptr=cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(pNode->name));
				attr = NTOHL(pNode->attributes);
				if (((attr & ATTR_INDEXCHILD) != ATTR_INDEXCHILD)||(*parent_nameptr == 'i')){
					strcat(defbuf, parent_nameptr);
					strcat(defbuf, "_");
					strcat(defbuf, tmpbuf);
				}
				else{
					strcat(defbuf, "i_");
					strcat(defbuf, tmpbuf);
				}
				/* athlon replace '-' to '_'  */
				rep(defbuf, "-", "_");
				memset(tmpbuf, 0, sizeof(tmpbuf));
				strcpy(tmpbuf, defbuf);

				pCurPList = pCurPList->next;
			}

			/*add object structure*/
			strcat(objbuf, tmpbuf);
			strcat(objbuf, "_s{\n");
			cmsXml_regParameter(node, objbuf);
			strcat(objbuf, "}cmsObj_");
			strcat(objbuf, tmpbuf);
			strcat(objbuf, "_t;\n");

			/*add object id & index node max num*/
			sprintf( cmsDefBuf, "#define OID_%s %d\n", tmpbuf, totalOIDNumber );
			rep(cmsDefBuf, "-", "_");
			strcat( objbuf, cmsDefBuf );
			if(*node_nameptr == 'i'){
				sprintf( cmsDefBuf, "#define %s_Max %d\n", tmpbuf, NTOHL(node->sibling.child_count));
				rep(cmsDefBuf, "-", "_");
				strcat( objbuf, cmsDefBuf );
				strcpy(cmsObjTmp, tmpbuf);
				rep(cmsObjTmp, "-", "_");
				sprintf(cmsObjBuf, "	{	\"%s\",	%d	},\n", cmsObjTmp, NTOHL(node->sibling.child_count));
				strcat(OBJ_MAXCOUNT, cmsObjBuf);
			}

			strcpy(cmsObjTmp, tmpbuf);
			rep(cmsObjTmp, "-", "_");
		}
		/*add content cms func header file & table file*/
#if 0
		cmsWriteRoutinehfile("db_", DBFUNC_HEADER , tmpbuf);
		cmsWriteRoutinetablefile("db_", DBFUNC_TABLE, tmpbuf, totalOIDNumber, 0);

		cmsWriteRoutinehfile("task_", TASKFUNC_HEADER, tmpbuf);
		cmsWriteRoutinetablefile("task_", TASKFUNC_TABLE, tmpbuf, totalOIDNumber, node->priority);
#endif
		
		if(node->updateObjFlag == 1){
			cmsWriteRoutinehfile("stats_", STATUSFUNC_HEADER, tmpbuf);
			cmsWriteRoutinetablefile("stats_", STATUSFUNC_TABLE, tmpbuf, totalOIDNumber, 0);
		}else{
			cmsWriteRoutinetablefile("stats_", STATUSFUNC_TABLE, "NULL", totalOIDNumber, 0);
		}

		fp = fopen(OBJ_HEADER,"a+"); 
		if(fp==NULL)
			goto errorReturn;
		fwrite(objbuf, sizeof(char), strlen(objbuf), fp);
      
		fclose(fp);
		

	}else{
		/*add OID cms header file & table file*/
	#if 0
		cmsWriteRoutinetablefile("cmsdb_", DBFUNC_TABLE, "NULL", totalOIDNumber, 0);
		cmsWriteRoutinetablefile("cmstask_", TASKFUNC_TABLE, "NULL", totalOIDNumber, 0);
	#endif
		cmsWriteRoutinetablefile("stats_", STATUSFUNC_TABLE, "NULL", totalOIDNumber, 0);

		/* write indexnode definition to cmsXml_object.h. */
		memset( cmsDefBuf, 0, sizeof( cmsDefBuf ) );
		rep(buf[ dest ], "-", "_");
		sprintf( cmsDefBuf, "#define OID_%s %d\n", buf[ dest ], totalOIDNumber );
		
		fp = fopen( OBJ_HEADER, "a+" ); 
		if ( fp == NULL )
			goto errorReturn;
		
		fwrite( cmsDefBuf, sizeof( char ), strlen( cmsDefBuf ), fp );
		fclose( fp );

	}
	
	strcat(namebuf, buf[dest]);
	strcat(namebuf, " ");

 	if (node->object){
		sprintf(id, "%d", (cmsoffset_t)NTOHDL(node->object)); 
	}
	else{
		/*if the node is not object node, use node's offset to be it's offset id*/
		offset = cmsXmlGetPtrOffset(xmlShmCb, node);
		sprintf(id, "%d", offset);

		/*assign non-object node's object value here!!*/
		node->object = HTONDL(offset);
	}
	strcat(namebuf, id);
	attr = NTOHL( node->attributes );

	/* work around for first object node. */
	memset( namebuf, 0, sizeof( namebuf ) );
	if ( ( !strcmp( fullpath[dest], "InternetGatewayDevice" ) ) && ( strlen( fullpath[dest] ) == strlen( "InternetGatewayDevice" ) ) )
	{
		sprintf( namebuf, "\n\t{\t%d,\t%s,\t\"%s\"\t, \t%d}", totalOIDNumber++, id, fullpath[dest], ((attr & ATTR_WRITABLE) ? 1: 0));
	}
	else
	{
		sprintf( namebuf, ",\n\t{\t%d,\t%s,\t\"%s\"\t, \t%d}", totalOIDNumber++, id, fullpath[dest], ((attr & ATTR_WRITABLE) ? 1: 0));
	}

	/* athlon replace '-' to '_'  */
	//rep(namebuf, "-", "_");
 
	fp = fopen(OBJIDTABLE_HEADER,"a+"); 
	if(fp==NULL)
		goto errorReturn;
	fwrite(namebuf, sizeof(char), strlen(namebuf), fp);
      
	fclose(fp);
	free(objbuf);
	
	return 0;

errorReturn:
	free(objbuf);
	return -1;
}

/*
	Description: 
		malloc for x2r, we pre-allocate a large memory for x2r,
		and cmsXml_Malloc() get the memory from the large memory for x2r.
		if the size of pre-allocate memory is not enough, 
		you need to modify the value of X2S_MEMORY_SIZE.
	Parameters:
		size: allocate size		
	return:
		return the pointer's offset
*/
cmsoffset_t cmsXml_Malloc(int size){
	cmsoffset_t offset;
	
	offset = current_offset;
	current_offset += size;
	total_size += size;

	if (total_size > X2S_MEMORY_SIZE){
		printf("the memory for x2r is not enough, please re-define the size\r\n");
		printf("total size:%x, memory size:%x\r\n", total_size, X2S_MEMORY_SIZE);
	}

	return offset;
}

/*
	Description: 
		malloc for x2r, we pre-allocate a large memory for x2r,
		and cmsXml_Malloc() get the memory from the large memory for x2r.
		if the size of pre-allocate memory is not enough, 
		you need to modify the value of X2S_MEMORY_SIZE.
	Parameters:
		size: allocate size		
	return:
		return the pointer's offset
*/
cmsoffset_t cmsXml_Free(int size){
	
	current_offset -= size;
	total_size -= size;

	return current_offset;
}


/*
	Description: 
		used to add new node
	Parameters:
		none		
	return:
		return the new node ptr
*/
objectNode_t *cmsXml_NewNode(void){
	/*allocate new node's space*/
	/*current_ptr jump to the address useable and the total size add the node size*/
	cmsoffset_t offset;
	objectNode_t *node;

	offset = cmsXml_Malloc(sizeof(objectNode_t));

	node = (objectNode_t *)(xmlShmCb->baseaddr+offset);

	return node;
}
/*
	Description: 
		set node's name
	Parameters:
		node: node ptr
		name: node name
	return:
		return CMS_OK
*/
int cmsXml_SetNodeName(objectNode_t *node, char *name){
	/*allocate name's space*/
	/*link to node*/
	int name_len;
	int name_pad;
	cmsoffset_t offset = 0;

	name_len = strlen(name) + 1; /*1 is for \0*/
	name_pad = name_len%BYTE_ALIGNS;
	if (name_pad != 0){
		name_pad = BYTE_ALIGNS - name_pad;
	}	

	offset = cmsXml_Malloc(name_len + name_pad);
	node->name = HTONDL(offset);
//	node->name_len = name_len -1;
//	memcpy((base_ptr+ node->name), name, node->name_len);
	strcpy((xmlShmCb->baseaddr+ offset), name);

	return CMS_OK;
}
/*
	Description: 
		link parent node's child to child
	Parameters:
		parent: parent ptr
		child: child ptr
	return:
		return CMS_OK
*/
int cmsXml_LinkChildNode(objectNode_t *parent, objectNode_t *child){

	/*parent's child should always link to the middle of child*/
	/*so we don't update the parent's child, unless parent's child is NULL (the first one)*/
//	child->parent = ((uint32_t)parent - (uint32_t)base_ptr);
	if (!(parent->child)){
		parent->child = HTONDL((uint32_t)child - (uint32_t)xmlShmCb->baseaddr);
	}

	return CMS_OK;
}
/*
	Description: 
		link sibling node, use AVL tree to link sibling nodes, parent's child would always point to the middle of children
	Parameters:
		parent: parent node
		addNode: new node to be added
	return:
		return CMS_OK
*/
int cmsXml_LinkSiblingNode(objectNode_t *parent, objectNode_t *addNode){
	/*should link the sibling node following by AVL tree*/
	/*accurate the middle and change the parent's child to the middle*/
	objectNode_t *newChild, *child = NULL;

	if (parent->child){
		child = (objectNode_t *)(xmlShmCb->baseaddr + NTOHDL(parent->child));
	}
	else{
		return CMS_NOK;
	}
	/*link the addNode and return the new middle node*/
	newChild = avlInsert(child, addNode);
	parent->child = HTONDL(cmsXmlGetPtrOffset(xmlShmCb, newChild));

	return CMS_OK;
}

/*
	Description: 
		link index node (index node means a.b.c.[i], i = 10)
	Parameters:
		node: index node (means c)
		number: index number (10)
		filterAttr: for indexchild's filter attributes // for xml parse PHASE_1
	return:
		return the first index child node (it will be a.b.c.i)
*/
objectNode_t *cmsXml_LinkIndexChild( objectNode_t *node, int number, cmsoffset_t filterAttr )
{
	uint32_t attr = 0;
	cmsoffset_t offset = 0;
	objectNode_t *child = NULL;

	offset = cmsXmlGetPtrOffset(xmlShmCb, node);

	child = cmsXml_NewNode();
	attr = ( ATTR_NODECONFIGURED | ATTR_INDEXCHILD );
	child->attributes = HTONL( attr );
	child->sibling.child_count = HTONL( number );
	cmsXml_SetNodeName( child, "i" );
	child->parent = HTONDL( offset );

	cmsXml_LinkChildNode(node, child);
		
	return child;
}


/*
	Description: 
		add parameter meta to node, if a node has parameter then it's a object node
		this function would set parameter's meta length, name, max and min value,
		parameter offset and type_size.
	Parameters:
		node: node ptr
		parameter: parameter structure pointer
	return:
		return CMS_OK
*/
int cmsXml_addParameter(objectNode_t *node, objParameter_t *parameter){
	/*allocate space for parameter, change current_ptr, add total size*/
	/*link parameter to node's parameter list*/
	uint32_t offset = 0;
	int size = 0, shift_offset = 0, meta_len = 0;
	int name_pad = 0;
	int name_length = 0;
	void *ptr, *ptr1, *shift_ptr = NULL, *meta_ptr = NULL,*configPadPtr = NULL, *nonConfigPadPtr = NULL;
	uint32_t type_size = 0, attr, config_size = 0, object_size = 0, para_size = 0, shift_size = 0, length = 0, configMeta_size = 0, totalMeta_size = 0;
	int shift = 0, shift_config = 0;
	int meta_count = 0;
	int meta_size = 0, pad_size = 0, pad_type = 0, isConfigPadded = 0, isNonConfigPadded = 0;
	cmsoffset_t meta_offset = 0, para_offset = 0;
	int configPadSize = 0, nonConfigPadSize = 0, configPadOriSize = 0, nonConfigPadOriSize = 0;

	name_length = strlen(parameter->name) + 1; /*1 is for \0*/
	/*for total length*/
	name_pad = (name_length + sizeof(uint8_t))%BYTE_ALIGNS;
	if (name_pad != 0){
		name_pad = BYTE_ALIGNS - name_pad;
	}
	/*2 is for parameter max, parameter min length*/
	/*1 is for type+parameter length*/
	/*2 is for parameter offset, attribute offset*/	
	meta_len = size = name_length + sizeof(uint8_t) + name_pad + sizeof(uint64_t)*2 +sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2;

	if (!node->meta){
		/*check first parameter need pad or not*/
		if (parameter->type == PARAMETER_TYPE_STRING){
			type_size = parameter->len;
		}
		else{
			type_size = parameter->type & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
		}
		pad_size = type_size%BYTE_ALIGNS;
		if (pad_size != 0){
			pad_size = BYTE_ALIGNS - pad_size;
			size += PADDING_META_LEN;
		}
		
		node->meta = HTONDL(cmsXml_Malloc(size));
		ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->meta));

		node->meta_count = 0;
		/*mark this node is an object node*/
		attr = NTOHL(node->attributes);
		attr |= ATTR_OBJECTNODE;
		node->attributes = HTONL(attr);
		if (pad_size != 0){
			if (parameter->config){
				configPadPtr = ptr + meta_len;
				configPadSize = pad_size;
			}
			else{
				nonConfigPadPtr = ptr + meta_len;
				nonConfigPadSize = pad_size;
			}
		}	
	}
	else{
		meta_ptr = ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->meta));
		meta_count = NTOHS(node->meta_count);

		if ((parameter->type != PARAMETER_TYPE_STRING)&&(parameter->type != PARAMETER_TYPE_DATETIME)){
			shift = 1;
			if (parameter->type == PARAMETER_TYPE_MAC){
				para_size = PARAMETER_TYPE_UINT8;
			}
			else{
				para_size = parameter->type & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
			}
		}
		config_size = NTOHL(node->config_size);
		/*
			shift_config case:
			case 1:	no config meta, add config meta
			case 2: no config meta, add non-config meta
			case 3: has config meta, add config meta
			case 4: has config meta, add non-config meta
		*/
		if ((config_size == 0)&&(parameter->config == 1)){
			shift_config = 1;
		}
		else if ((config_size == 0)&&(parameter->config == 0)){
			shift_config = 2;
		}
		else if ((config_size != 0)&&(parameter->config == 1)){
			shift_config = 3;
		}	
		else if ((config_size != 0)&&(parameter->config == 0)){
			shift_config = 4;
		}		
		while(meta_count){
			memcpy(&meta_size, ptr, sizeof(uint8_t));

			if (meta_size == PADDING_META_LEN){
				/*this meta is padding meta*/
				/*the fourth byte is padding size*/
				memcpy(&pad_size, (ptr+sizeof(uint8_t)*3), sizeof(uint8_t));
				memcpy(&pad_type, (ptr+sizeof(uint8_t)), sizeof(uint8_t));
				type_size = pad_size;
				if (pad_type == 1){
					isConfigPadded = 1;
					configPadOriSize = pad_size;
				}
				else{
					isNonConfigPadded = 1;
					nonConfigPadOriSize = pad_size;
				}
			}
			else{
				/*get type_size*/
				memcpy(&type_size, (ptr+meta_size-sizeof(uint32_t)), sizeof(uint32_t));
				type_size = NTOHL(type_size);
			}

			if (shift_config == 1){
				/*shift all other meta*/
				if (shift_ptr == NULL){
					shift_ptr = ptr;
				}
				shift_size += meta_size;
				shift = 1;	/*all non-config meta needs to shift*/
			}
			else if (shift_config == 2){
				/*there is no config parameter, insert the parameter to non-config parameters*/
				/*check parameter size to decide shift parameter or not*/
				if (type_size == PARAMETER_TYPE_MAC){
					length = PARAMETER_TYPE_UINT8;
				}
				else{
					length = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
				}
				if (shift){
					/*if the meta is string or other type which use char xxx[], shift it*/
					if (((type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING) || (type_size == PARAMETER_TYPE_DATETIME) || (meta_size == PADDING_META_LEN)){
						if ((shift_ptr == NULL)&&(meta_size != PADDING_META_LEN)){
							shift_ptr = ptr;
						}
						if (shift_ptr != NULL)
							shift_size += meta_size;
					}
					else if (para_size > length){
						/*if meta is not string, check size*/
						if (shift_ptr == NULL){
							shift_ptr = ptr;
						}					
						shift_size += meta_size;
					}
				}				
			}
			else if (shift_config == 3){
				/*there is config parameters and the parameter is config, insert the parameter to config parameters*/
				if (config_size == 0){
					/*if the meta is non-config, shift it*/
					/*shift all other non-config meta*/
					if (shift_ptr == NULL){
						shift_ptr = ptr;
					}
					shift_size += meta_size;
					shift = 1;	/*all other non-config meta needs shift*/
				}
				else{
					/*check parameter size to decide shift parameter or not*/
					if (type_size == PARAMETER_TYPE_MAC){
						length = PARAMETER_TYPE_UINT8;
					}
					else{
						length = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
					}
					if (shift){
						/*if the meta is string or other type which use char xxx[], shift it*/
						if (((type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING) || (type_size == PARAMETER_TYPE_DATETIME) || (meta_size == PADDING_META_LEN)){
							if ((shift_ptr == NULL)&&(meta_size != PADDING_META_LEN)){
								shift_ptr = ptr;
							}
							if (shift_ptr != NULL)
								shift_size += meta_size;
						}
						else if (para_size > length){
							/*if meta is not string, check size*/
							if (shift_ptr == NULL){
								shift_ptr = ptr;
							}					
							shift_size += meta_size;
						}
					}
					configMeta_size += meta_size;
					config_size -= (type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS));
				}
			}
			else if (shift_config == 4){
				/*there is config parameters and the parameter is non-config, insert the parameter to non-config parameters*/
				if (config_size != 0){
					/*if the meta is config,  don't shift it*/
					config_size -= (type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS));
				}
				else{
					/*check parameter size to decide shift parameter or not*/
					if (type_size == PARAMETER_TYPE_MAC){
						length = PARAMETER_TYPE_UINT8;
					}
					else{
						length = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
					}
					if (shift){
						/*if the meta is string or other type which use char xxx[], shift it*/
						if (((type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING) || (type_size == PARAMETER_TYPE_DATETIME)||(meta_size == PADDING_META_LEN)){
							if ((shift_ptr == NULL)&&(meta_size != PADDING_META_LEN)){
								shift_ptr = ptr;
							}
							if (shift_ptr != NULL)
								shift_size += meta_size;
						}
						else if (para_size > length){
							/*if meta is not string, check size*/
							if (shift_ptr == NULL){
								shift_ptr = ptr;
							}					
							shift_size += meta_size;
						}
					}
				}
			}			
			/*remove the first two bits to get the real parameter size*/
			type_size &= ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
			
			para_offset += type_size;
			totalMeta_size += meta_size;
			ptr = ptr + meta_size;
			meta_count--;			
		}

		/*get size of add parameter*/
		if (parameter->type == PARAMETER_TYPE_STRING){
			type_size = parameter->len;
		}
		else{
			type_size = parameter->type & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
		}
		if (shift_config == 1){
			/*add a new config meta, check padding*/
			pad_size = type_size%BYTE_ALIGNS;
			if (pad_size != 0){
				pad_size = BYTE_ALIGNS - pad_size;
				if (shift_ptr != NULL){
					configPadPtr = shift_ptr + size;
					configPadSize = pad_size;
				}
				size += PADDING_META_LEN;
			}
			shift_offset = size;
		}
		else if (shift_config == 2){
			/*no matter padding or not, shift meta size*/
			shift_offset = size;
			/*re-calculate allocate size*/
			if (isNonConfigPadded){
				size -= PADDING_META_LEN;
			}
			object_size = NTOHL(node->object_size);
			pad_size = ((object_size - nonConfigPadOriSize) + type_size)%BYTE_ALIGNS;
			if (pad_size != 0){
				pad_size = BYTE_ALIGNS - pad_size;
				nonConfigPadPtr = ptr + size;  
				nonConfigPadSize = pad_size;
				size += PADDING_META_LEN;
			}
		}
		else if (shift_config == 3){
			/*
				case 1, no non-config, has pad
				case 2, no non-config, no pad
				case 3, has non-config, has pad
					3.1, need shift config meta
					3.2, only shift non-config meta
				case 4, has non-config, no pad
					4.1, need shift config meta
					4.2, only shift non-config meta				

			*/
			shift_offset = size;
			/*re-calculate allocate size*/
			if (isConfigPadded){
				size -= PADDING_META_LEN;
			}
			config_size = NTOHL(node->config_size);
			object_size = NTOHL(node->object_size);
			pad_size = ((config_size - configPadOriSize) + type_size)%BYTE_ALIGNS;
			if (pad_size != 0){
				pad_size = BYTE_ALIGNS - pad_size;
				if (shift_ptr == NULL){	/*case 1 or case 2*/
					configPadPtr =  ptr + size;  
					configPadSize = pad_size;					
				}
				else{	/*case 3 or case 4*/
					configPadPtr = meta_ptr + configMeta_size + size;
					configPadSize = pad_size;
				}

				size += PADDING_META_LEN;
			}
			if ((shift_ptr != NULL)&&(shift_ptr == meta_ptr + configMeta_size)){
				/*if it only need to shift non-config meta, re-calculate shift_size*/
				shift_offset = size;
			}
		}
		else if (shift_config == 4){
			shift_offset = size;
			/*re-calculate allocate size*/
			if (isNonConfigPadded){
				size -= PADDING_META_LEN;
			}
			config_size = NTOHL(node->config_size);
			object_size = NTOHL(node->object_size);
			pad_size = ((object_size - config_size - nonConfigPadOriSize) + type_size)%BYTE_ALIGNS;
			if (pad_size != 0){
				pad_size = BYTE_ALIGNS - pad_size;
				nonConfigPadPtr = ptr + size;  
				nonConfigPadSize = pad_size;
				size += PADDING_META_LEN;
			}			
		}		
		meta_offset = cmsXml_Malloc(size);
		ptr1 = cmsXmlGetObjRealAddr(xmlShmCb, meta_offset);
		if (ptr != ptr1){
			printf("error!!!!parameter meta should be put side by side!! ptr:%x, ptr1:%x\r\n", (uint32_t)ptr, (uint32_t)ptr1);
		}
	}
	/*shift meta data*/
	if ((shift)&&(shift_ptr != NULL)){
		if (shift_config == 3){
			if (shift_ptr == (meta_ptr + configMeta_size)){
				memmove(shift_ptr+ shift_offset, shift_ptr, shift_size);
				ptr = shift_ptr;
			}
			else if (configMeta_size == totalMeta_size){
				/*there is no non-config meta, only move config meta*/
				/*move config meta*/
				if ((configPadPtr == NULL)&&(isConfigPadded != 0)){	
					/*no move pad*/
					memmove(shift_ptr+ shift_offset, shift_ptr, (shift_size - (totalMeta_size - configMeta_size) - 4));
				}
				else{	
					/*also move pad*/
					
					memmove(shift_ptr+ shift_offset, shift_ptr, (shift_size - (totalMeta_size - configMeta_size)));
				}
				ptr = shift_ptr;				
			}
			else{
				/*move non-config meta*/

				memmove(meta_ptr + configMeta_size + size, meta_ptr + configMeta_size, (totalMeta_size - configMeta_size));

				/*move config meta*/
				if ((configPadPtr == NULL)&&(isConfigPadded != 0)){	
					/*no move pad*/
					memmove(shift_ptr+ shift_offset, shift_ptr, (shift_size - (totalMeta_size - configMeta_size) - 4));
				}
				else{	
					/*also move pad*/
					
					memmove(shift_ptr+ shift_offset, shift_ptr, (shift_size - (totalMeta_size - configMeta_size)));
				}
				ptr = shift_ptr;
			}
		}
		else{
			memmove(shift_ptr+ shift_offset, shift_ptr, shift_size);
			ptr = shift_ptr;
		}
	}
	if (((shift_config == 2) || (shift_config == 4))&&(isNonConfigPadded == 1)&&(shift_ptr == NULL)){
		ptr -= PADDING_META_LEN;
	}
	if ((shift_config == 3)&&(isConfigPadded == 1)&&((shift_ptr == NULL)||(shift_ptr == (meta_ptr + configMeta_size)))){
		ptr -= PADDING_META_LEN;
	}
	
	/*total length*/
	memcpy(ptr+offset, &meta_len, sizeof(uint8_t));
	offset += sizeof(uint8_t);
	/*name*/
	strcpy(ptr+offset, parameter->name);
	offset += name_length + name_pad;
	switch (parameter->type){
	case PARAMETER_TYPE_UINT8:
	case PARAMETER_TYPE_BOOLEAN:
		/*parameter max*/
		memcpy(ptr+offset, &parameter->max.unsign.u8, sizeof(uint8_t));
		offset += sizeof(uint64_t);		
		/*parameter min*/
		memcpy(ptr+offset, &parameter->min.unsign.u8, sizeof(uint8_t));
		offset += sizeof(uint64_t);			
		break;
	case PARAMETER_TYPE_UINT16:
		/*parameter max*/
		memcpy(ptr+offset, &parameter->max.unsign.u16, sizeof(uint16_t));
		offset += sizeof(uint64_t);		
		/*parameter min*/
		memcpy(ptr+offset, &parameter->min.unsign.u16, sizeof(uint16_t));
		offset += sizeof(uint64_t);	
		break;
	case PARAMETER_TYPE_UINT32:
		/*parameter max*/
		memcpy(ptr+offset, &parameter->max.unsign.u32, sizeof(uint32_t));
		offset += sizeof(uint64_t);		
		/*parameter min*/
		memcpy(ptr+offset, &parameter->min.unsign.u32, sizeof(uint32_t));
		offset += sizeof(uint64_t);				
		break;
	case PARAMETER_TYPE_MAC:
		offset += sizeof(uint64_t);
		offset += sizeof(uint64_t);
		break;	
	case PARAMETER_TYPE_UINT64:
		/*parameter max*/
		memcpy(ptr+offset, &parameter->max.unsign.u64, sizeof(uint64_t));
		offset += sizeof(uint64_t);		
		/*parameter min*/
		memcpy(ptr+offset, &parameter->min.unsign.u64, sizeof(uint64_t));
		offset += sizeof(uint64_t);					
		break;
	case PARAMETER_TYPE_SINT7:
		/*parameter max*/
		memcpy(ptr+offset, &parameter->max.sign.s7, sizeof(int8_t));
		offset += sizeof(uint64_t);		
		/*parameter min*/
		memcpy(ptr+offset, &parameter->min.sign.s7, sizeof(int8_t));
		offset += sizeof(uint64_t);					
		break;
	case PARAMETER_TYPE_SINT15:
		/*parameter max*/
		memcpy(ptr+offset, &parameter->max.sign.s15, sizeof(int16_t));
		offset += sizeof(uint64_t);		
		/*parameter min*/
		memcpy(ptr+offset, &parameter->min.sign.s15, sizeof(int16_t));
		offset += sizeof(uint64_t);				
		break;
	case PARAMETER_TYPE_SINT31:
		/*parameter max*/
		memcpy(ptr+offset, &parameter->max.sign.s31, sizeof(int32_t));
		offset += sizeof(uint64_t);		
		/*parameter min*/
		memcpy(ptr+offset, &parameter->min.sign.s31, sizeof(int32_t));
		offset += sizeof(uint64_t);					
		break;
	case PARAMETER_TYPE_SINT63:
		/*parameter max*/
		memcpy(ptr+offset, &parameter->max.sign.s63, sizeof(int64_t));
		offset += sizeof(uint64_t);		
		/*parameter min*/
		memcpy(ptr+offset, &parameter->min.sign.s63, sizeof(int64_t));
		offset += sizeof(uint64_t);					
		break;
	case PARAMETER_TYPE_STRING:
	case PARAMETER_TYPE_DATETIME:
		offset += sizeof(uint64_t);
		offset += sizeof(uint64_t);
		break;		
	}	
	
	/*parameter offset*/
	para_offset = HTONDL(para_offset);
	memcpy(ptr+offset, &para_offset, sizeof(cmsoffset_t));
	offset += sizeof(cmsoffset_t);	
	/*attribute offset would be calculate later*/
	offset += sizeof(cmsoffset_t);
	/*type+size*/
	if (parameter->type == PARAMETER_TYPE_STRING){	/*only string needs to calculate type_size*/
		type_size = HTONL(PARAMETER_TYPE_STRING + parameter->len);
		memcpy(ptr+offset, &type_size, sizeof(uint32_t));
		if (parameter->config){
			config_size = NTOHL(node->config_size);
			config_size += (parameter->len - configPadOriSize + configPadSize);
			node->config_size = HTONL(config_size);
		}
		object_size = NTOHL(node->object_size);
		if (shift_config == 4){
			/*at case 4, don't care config Pad Size*/
			configPadSize = 0;
			configPadOriSize = 0;
		}
		else if ((shift_config == 1)||(shift_config == 3)){
			/*at case 1 or case 3. don't care non-config pad size*/
			nonConfigPadSize = 0;
			nonConfigPadOriSize = 0;
		}
		object_size += (parameter->len + configPadSize + nonConfigPadSize - configPadOriSize - nonConfigPadOriSize);
		node->object_size = HTONL(object_size);		
	}
	else{	/*for other type, type is their type_size*/
		type_size = HTONL(parameter->type);
		memcpy(ptr+offset, &type_size, sizeof(uint32_t));

		type_size = parameter->type;
		type_size &= ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
		if (parameter->config){
			config_size = NTOHL(node->config_size);
			config_size += (type_size + - configPadOriSize + configPadSize);
			node->config_size = HTONL(config_size);
		}
		object_size = NTOHL(node->object_size);
		if (shift_config == 4){
			/*at case 4, don't care config Pad Size*/
			configPadSize = 0;
			configPadOriSize = 0;
		}
		else if ((shift_config == 1)||(shift_config == 3)){
			/*at case 1 or case 3. don't care non-config pad size*/
			nonConfigPadSize = 0;
			nonConfigPadOriSize = 0;
		}		
		object_size += (type_size + configPadSize + nonConfigPadSize - configPadOriSize - nonConfigPadOriSize);
		node->object_size = HTONL(object_size);			
	}
	meta_count = NTOHS(node->meta_count);
	meta_count += 1;
	node->meta_count = HTONS(meta_count);

	/*set padding meta value*/
	offset = 0;
	size = PADDING_META_LEN;
	if (configPadPtr != NULL){
		memcpy(configPadPtr+offset, &size, sizeof(uint8_t));
		offset += sizeof(uint8_t);
		pad_type = 1;
		memcpy(configPadPtr+offset, &pad_type, sizeof(uint8_t));
		offset += sizeof(uint8_t)*2;
		memcpy(configPadPtr+offset, &configPadSize, sizeof(uint8_t));
		if (isConfigPadded == 0){
			meta_count = NTOHS(node->meta_count);
			meta_count += 1;
			node->meta_count = HTONS(meta_count);
		}
	}
	else if ((isConfigPadded == 1)&&(shift_config != 4)){
		meta_count = NTOHS(node->meta_count);
		meta_count -= 1;
		node->meta_count = HTONS(meta_count);
	}
	offset = 0;
	if (nonConfigPadPtr != NULL){
		memcpy(nonConfigPadPtr+offset, &size, sizeof(uint8_t));
		offset += sizeof(uint8_t);
		pad_type = 0;
		memcpy(nonConfigPadPtr+offset, &pad_type, sizeof(uint8_t));		
		offset += sizeof(uint8_t)*2;
		memcpy(nonConfigPadPtr+offset, &nonConfigPadSize, sizeof(uint8_t));
		if (isNonConfigPadded == 0){
			meta_count = NTOHS(node->meta_count);
			meta_count += 1;
			node->meta_count = HTONS(meta_count);
		}		
	}
	else if ((isNonConfigPadded == 1)&&(shift_config != 1)&&(shift_config != 3)){
		meta_count = NTOHS(node->meta_count);
		meta_count -= 1;
		node->meta_count = HTONS(meta_count);
	}	
	return CMS_OK;
}
/*
	Description: 
		allocate object memory for index child node, if the index child is an object node
		it will use cmsXml_NodeCopyObject() allocate object data memory to other index child
		node.
	Parameters:
		node: the first index child node
	return:
		return CMS_OK
*/
int cmsXml_IndexChildAddObject(objectNode_t *node){
	objectNode_t *next;
	int i = 1,count= 0;
	uint32_t attr = 0;

	attr = NTOHL(node->attributes);
	
	if ((node->meta_count == 0)&&(( attr & ATTR_INDEXNODE) != ATTR_INDEXNODE)){
		return CMS_OK;
	}
	count = NTOHL(node->sibling.child_count);
	while (count > 0){
		next = node + i;
		cmsXml_NodeCopyObject(node, next);
		i++;
		count--;
	}
	return CMS_OK;
}

/*
	Description: 
		copy object data from src to dst
	Parameters:
		src node: src node
		dst node: dst node
	return:
		return CMS_OK
*/
int cmsXml_NodeCopyObjectData(objectNode_t *src, objectNode_t *dst){
	char *ptr, *ptr1;

	if (src->object_size == 0){
		return CMS_OK;
	}
	
	ptr = (xmlShmCb->baseaddr + NTOHDL(dst->object));
	ptr1 = (xmlShmCb->baseaddr + NTOHDL(src->object));
	memcpy(ptr, ptr1, NTOHL(src->object_size));

	return CMS_OK;
}
/*
	Description: 
		1. copy object data to other index child from the first index child node
		2. register the object id to rdm_obj_id.h by cms_regObjectId()
	Parameters:
		node: the first index child node
		pList: the parent list
	return:
		return CMS_OK
*/
int cmsXml_indexChildCopyObjectData(objectNode_t *node, parentList_t *pList){
	objectNode_t *next;
	uint32_t attr = 0;
	int i = 1, count = 0;

	attr = NTOHL(node->attributes);
	if (!( attr & ATTR_INDEXCHILD)){
		return CMS_OK;
	}
	count = NTOHL(node->sibling.child_count);
	while (count > 0){
		next = node + i;
		cmsXml_NodeCopyObjectData(node, next);
		cmsXml_regObjectId(next, pList);
		i++;
		count--;
	}		
	return CMS_OK;
}

/*
	Description: 
		copy leaf node to leaf node
		1. copy node's meta, object size, meta_count...
		2. if the src node is an object node, copy object data and register obj id
		otherwise, register obj id only (for object change event use).
	Parameters:
		src: source node
		dst: dst node
		pList: parent list
		nameSrc: name's src. // for xml parse PHASE 1
	return:
		return CMS_OK
*/
int cmsXml_CopyNodeToNode(objectNode_t *src, objectNode_t *dst, parentList_t *pList, objectNode_t *nameSrc){
	uint32_t attr = 0;

	/*besides child, prev, next, object, others are the same*/
	dst->height = src->height;
	dst->name = src->name;
	dst->meta = src->meta;
	dst->object_size = src->object_size;
	dst->config_size = src->config_size;
	dst->attributes = src->attributes;
	dst->meta_count = src->meta_count;

	attr = NTOHL(src->attributes);
#ifdef CMS_XML_PARSE_PHASE_1
	if ( !(attr & ATTR_FILTERONLYNODE) ) dst->name = nameSrc->name;
#endif
	if ((src->meta_count != 0)||(( attr & ATTR_INDEXNODE) == ATTR_INDEXNODE)){
		/*copy object*/

		cmsXml_NodeCopyObject(src, dst);
		/*copy object data*/
		cmsXml_NodeCopyObjectData(src, dst);
		cmsXml_regObjectId(dst, pList);
	}
	else{
		cmsXml_regObjectId(dst, pList);
	}
	return CMS_OK;
}

#if 0
/*
	Description: 
		copy node to node, including node's child list, 
		all nodes belong to src node would be copyed to the dst node
		if the src node is an index child, all other index child will copy src's node child list.
	Parameters:
		src: source node
		pList: parent list
	return:
		return the new node offset
	called by:
		cmsXml_IndexChildCopyNode()		
*/
cmsoffset_t cmsXml_CopyNode(objectNode_t *src, parentList_t *pList){
	objectNode_t *tnode, *child = NULL, *tmp = NULL, *next, *prev;
	parentList_t *list;
	cmsoffset_t offset;
	uint32_t attr = 0;
	int i = 0, count = 0;
#ifdef CMS_XML_PARSE_PHASE_1
	objectNode_t *pNode = NULL;
	cmsoffset_t filterAttr = 0;
	char *namePtr = NULL;
	int checkCopyNodeFlag = CMS_NOK; // OK: copy object offset, NOK: allocate object.
#endif

	attr = NTOHL(src->attributes);
	if (( attr & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
		count = NTOHL(src->sibling.child_count);
		while(count >= 0){
			attr = 0;
			tnode = cmsXml_NewNode();
			attr |= ATTR_INDEXCHILD;
//			attr |= ATTR_LEAFCHILD;
			tnode->attributes = HTONL(attr);
			tnode->sibling.child_count = src->sibling.child_count;
			offset = cmsXmlGetPtrOffset(xmlShmCb, pList->node);
			tnode->parent = HTONDL(offset);
			if (i == 0){
				tmp = tnode;
			}
			count--;
			i++;
		}

		count =NTOHL( src->sibling.child_count);
		i = 0;
		if (src->child){
			child = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->child));
		}
		while (count >= 0){
			next = src + i;
			tnode = tmp + i;
#ifdef CMS_XML_PARSE_PHASE_1
			attr = NTOHL(next->attributes);
			if( attr & ATTR_FILTERONLYNODE ) // check src node is ONLY node.
			{
				pNode = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(tnode->parent)); // get parent node.
				checkCopyNodeFlag = CMS_NOK; // default is allocate object space.
				while( pNode ) // check all parent's name is i.
				{
					filterAttr = NTOHL(pNode->attributes); // get parent attributes.
					if( filterAttr & ATTR_INDEXCHILD ) // only check indexChild name.
					{
						namePtr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(pNode->name));
						// just one node if node name != i and attr != ATTR_FILTEREVERYNODE, then mark copy object offset.
						if( stricmp( namePtr, "i" ) && !(filterAttr & ATTR_FILTEREVERYNODE) )
						{
							checkCopyNodeFlag = CMS_OK;
						}
					}
					pNode = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(pNode->parent));
				}
				if( checkCopyNodeFlag == CMS_OK ) // copy node structure and copy object offset.
				{
					tnode->height = next->height;
					tnode->name = next->name;
					tnode->meta = next->meta;
					tnode->object_size = next->object_size;
					tnode->config_size = next->config_size;
					tnode->attributes = next->attributes;
					tnode->meta_count = next->meta_count;
					tnode->object = next->object; // copy object offset.
					
					namePtr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(next->name));
					if ( !stricmp( namePtr, "i" ) )
					{
						filterAttr = NTOHL(next->attributes);
						filterAttr &= ~ATTR_NODECONFIGURED;
						tnode->attributes = HTONL(filterAttr);
					}
					else
						tnode->attributes = next->attributes;
	
					if ( next->meta_count != 0 )
					{
						filterAttr = NTOHL(next->attributes);
						filterAttr |= ATTR_OBJECTNODE;
						tnode->attributes = HTONL(filterAttr);
					}
					cmsXml_regObjectId(tnode, pList);
				}
				else // allocate object space, all parent's name equals to i except EVERY node.
				{
					cmsXml_CopyNodeToNode(next, tnode, pList, next);
				}
			}
			else // src node is not ONLY node, we allocate object space.
			{
				if( i == 0 ) // means dst node name is i, just copy src node.
				{
					cmsXml_CopyNodeToNode(next, tnode, pList, next);
				}
				else // copy from indexchild i.
					cmsXml_CopyNodeToNode(src, tnode, pList, next);
			}
#else
			cmsXml_CopyNodeToNode(next, tnode, pList, next);
#endif
			i++;
			count--;
		}
		/*move child out for all index child object node should be node by node*/
		if (child){
			count =NTOHL( src->sibling.child_count);
			i = 0;			
			while (count >= 0){
			/*copy child's next*/
				tnode = tmp + i;
				list = (struct parentList_s *)malloc(sizeof(struct parentList_s));
				list->node = tnode;
				list->next = pList;
#ifdef CMS_XML_PARSE_PHASE_1
				if ( i > 0 ) // copy from indexchild i.
				{
					tnode->child = HTONDL(cmsXml_CopyNode(((objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(tmp->child))), list));
				}
				else // copy from src node.
					tnode->child = HTONDL(cmsXml_CopyNode(child, list));
#else
				tnode->child = HTONDL(cmsXml_CopyNode(child, list));				
#endif
				
				free(list);

				i++;
				count--;
			}
		}
		
		
		offset = cmsXmlGetPtrOffset(xmlShmCb, tmp);
		return offset;

	}
	/*besides child, prev, next, object, others are the same*/

	/*copy node's child*/
	if(!(tnode = cmsXml_NewNode()))
	{
		printf("cmsXml_IndexChildCopyNode: no mem\n");
		return CMS_NOK;
	}

	cmsXml_CopyNodeToNode(src, tnode, pList, src);
	
//			cmsXml_LinkChildNode(prev, tnode);
//			cmsXml_LinkSiblingNode(prev, tnode);

	offset = cmsXmlGetPtrOffset(xmlShmCb, pList->node);
	tnode->parent = HTONDL(offset);
			
	if (src->sibling.tree.prev){
		prev = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->sibling.tree.prev));
		/*copy child's prev*/
		tnode->sibling.tree.prev = HTONDL(cmsXml_CopyNode(prev, pList));
	}

	if (src->sibling.tree.next){
		next = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->sibling.tree.next));
		/*copy child's next*/
		tnode->sibling.tree.next = HTONDL(cmsXml_CopyNode(next, pList));				
	}

	if (src->child){
		child = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->child));
		/*copy child's next*/
		list = (struct parentList_s *)malloc(sizeof(struct parentList_s));
		list->node = tnode;
		list->next = pList;	
		tnode->child = HTONDL(cmsXml_CopyNode(child, list));				
		free(list);
	}

	offset = cmsXmlGetPtrOffset(xmlShmCb, tnode);
	return offset;
}
#endif
/*
	Description: 
		copy node list to other index child from the first index child node
	Parameters:
		node: the first index child node
		pList: parent list
	return:
		return CMS_OK
*/
int cmsXml_IndexChildCopyNode( objectNode_t *node, parentList_t *pList )
{
	objectNode_t *child = NULL;
#ifdef XML_TEST_DEBUG
	uint32_t attr = 0;
	int count = 0;
	attr = NTOHL(node->attributes);
	count = NTOHL(node->sibling.child_count);
	printf("child count %d, attr 0x%x\n", count, attr);
#endif
	if (node->child){
		child = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->child));
		if(child == NULL){
			return CMS_NOK;
		}
	}

	return CMS_OK;
}

/*
	Description: 
		allocate object structure memory to dst node and copy from src
	Parameters:
		src node: source node
		dst node: dst node
	return:
		return CMS_OK
	called by:
		cmsXml_IndexChildAddObject() and cmsXml_CopyNodeToNode()
*/
int cmsXml_NodeCopyObject(objectNode_t *src, objectNode_t *dst){
	cmsoffset_t offset, ptrOffset;
	uint32_t padding = 0, object_size = 0;
	void *ptr;
	uint32_t attr = 0;
	char *name;
	int count = 3;

	/*check copy object's problem of i node offset*/
	attr = NTOHL(src->attributes);

	object_size = NTOHL(src->object_size);
	padding = object_size%BYTE_ALIGNS;
	if (padding != 0){
		padding = BYTE_ALIGNS - padding;
	}
	/*add object padding to 4 bytes*/
	offset = cmsXml_Malloc(NTOHL(src->object_size) + sizeof(cmsoffset_t)*count + padding);	/*object size + meta pointer + node pointer + timestamp*/
	dst->object = HTONDL(offset + sizeof(cmsoffset_t)*count);	/*object offset needs to decrease (meta pointer + node pointer + timestamp)*/
	ptr = cmsXmlGetObjRealAddr(xmlShmCb, (NTOHDL(dst->object) - sizeof(cmsoffset_t)));
	memcpy(ptr , &src->meta, sizeof(cmsoffset_t));
	ptr = cmsXmlGetObjRealAddr(xmlShmCb, (NTOHDL(dst->object) - sizeof(cmsoffset_t)*2));
	ptrOffset = HTONDL(cmsXmlGetPtrOffset(xmlShmCb, dst));
	memcpy(ptr, &ptrOffset, sizeof(cmsoffset_t));
	
	dst->meta = src->meta;
	dst->object_size = src->object_size;
	dst->config_size = src->config_size;
	name = cmsXmlGetObjRealAddr(xmlShmCb, NTOHL(src->name));
	if (!strcmp(name, "i")){
		attr = NTOHL(src->attributes);
		attr &= ~ATTR_NODECONFIGURED;
		dst->attributes = HTONL(attr);
	}
	else{
		dst->attributes = src->attributes;
	}
	dst->meta_count = src->meta_count;
	
	if (src->meta_count != 0){
		attr = NTOHL(dst->attributes);
		attr |= ATTR_OBJECTNODE;
		dst->attributes = HTONL(attr);
	}

	return CMS_OK;
}

static int cmsFinRoutinehfile(void)
{
	FILE *fp = NULL;
	char headerBuf[BUFLEN_256] = {0};

#if 0
	/*db func file*/
	strcat(headerBuf, "#endif\n");
	fp = fopen(DBFUNC_HEADER,"a+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", DBFUNC_HEADER);
		return -1;
	}
	fwrite(headerBuf, sizeof(char), strlen(headerBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*task func file*/
	memset(headerBuf, 0, sizeof(headerBuf));
	strcat(headerBuf, "#endif\n");
	fp = fopen(TASKFUNC_HEADER,"a+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", TASKFUNC_HEADER);
		return -1;
	}
	fwrite(headerBuf, sizeof(char), strlen(headerBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*db table file*/
	memset(headerBuf, 0, sizeof(headerBuf));
	strcat(headerBuf, TABLE_FILE_TAIL);
	fp = fopen(DBFUNC_TABLE,"a+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", DBFUNC_TABLE);
		return -1;
	}
	fwrite(headerBuf, sizeof(char), strlen(headerBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*task table file*/
	fp = fopen(TASKFUNC_TABLE,"a+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", TASKFUNC_TABLE);
		return -1;
	}
	fwrite(headerBuf, sizeof(char), strlen(headerBuf), fp);      
	fclose(fp);
	fp = NULL;
#endif

	/*task stats file*/
	memset(headerBuf, 0, sizeof(headerBuf));
	strcat(headerBuf, "#endif\n");
	fp = fopen(STATUSFUNC_HEADER,"a+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", STATUSFUNC_HEADER);
		return -1;
	}
	fwrite(headerBuf, sizeof(char), strlen(headerBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*task stats file*/
	memset(headerBuf, 0, sizeof(headerBuf));
	strcat(headerBuf, TABLE_FILE_TAIL);
	fp = fopen(STATUSFUNC_TABLE,"a+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", STATUSFUNC_TABLE);
		return -1;
	}
	fwrite(headerBuf, sizeof(char), strlen(headerBuf), fp);      
	fclose(fp);

	return 0;
}

static int cmsInitRoutinehfile(void)
{
	FILE *fp = NULL;
	char cmsFuncFileBuf[BUFLEN_256] = {0};

	/*
	*create header .h file.
	*/

#if 0	
	/*create cmsDb func header file*/
	strcat(cmsFuncFileBuf, "#ifndef _DB_FUNC_H\n");
	strcat(cmsFuncFileBuf, "#define _DB_FUNC_H\n");
	fp = fopen(DBFUNC_HEADER,"w+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", DBFUNC_HEADER);
		return -1;
	}
	fwrite(cmsFuncFileBuf, sizeof(char), strlen(cmsFuncFileBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*create cmsTask func header file*/
	memset(cmsFuncFileBuf, 0, sizeof(cmsFuncFileBuf));
	strcat(cmsFuncFileBuf, "#ifndef _TASK_FUNC_H\n");
	strcat(cmsFuncFileBuf, "#define _TASK_FUNC_H\n");
	fp = fopen(TASKFUNC_HEADER,"w+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", TASKFUNC_HEADER);
		return -1;
	}
	fwrite(cmsFuncFileBuf, sizeof(char), strlen(cmsFuncFileBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*
	*create func file .c file.
	*/
	/*create cms db func file.*/	
	memset(cmsFuncFileBuf, 0, sizeof(cmsFuncFileBuf));
	strcat(cmsFuncFileBuf, "#include <stdlib.h>\n");
	strcat(cmsFuncFileBuf, "#include \"cms_common.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"cmsXml_object.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"cms_objFunc.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"cmsDb_routineFunc.h\"\n\n\n");
	strcat(cmsFuncFileBuf, "const cmsObjFunc_t db_objFuncTable[]={\n");
	fp = fopen(DBFUNC_TABLE,"w+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", DBFUNC_TABLE);
		return -1;
	}
	fwrite(cmsFuncFileBuf, sizeof(char), strlen(cmsFuncFileBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*create cms task func file.*/
	memset(cmsFuncFileBuf, 0, sizeof(cmsFuncFileBuf));
	strcat(cmsFuncFileBuf, "#include <stdlib.h>\n");
	strcat(cmsFuncFileBuf, "#include \"cms_common.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"libmdm.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"cmsXml_object.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"cms_objFunc.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"cmsTask_utils.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"cmsTask_routineFunc.h\"\n\n\n");
	strcat(cmsFuncFileBuf, "const cmsObjFunc_t task_objFuncTable[]={\n");
	fp = fopen(TASKFUNC_TABLE,"w+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", TASKFUNC_TABLE);
		return -1;
	}
	fwrite(cmsFuncFileBuf, sizeof(char), strlen(cmsFuncFileBuf), fp);      
	fclose(fp);
	fp = NULL;
#endif

	/*create cmsTask stats header file*/

	fp = fopen(STATUSFUNC_HEADER,"w+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", STATUSFUNC_HEADER);
		return -1;
	}

	sprintf(cmsFuncFileBuf, "/* Date:%s %s Auto Generated at building time, do not edit it. */\n\n", __DATE__, __TIME__);
	fwrite(cmsFuncFileBuf, sizeof(char), strlen(cmsFuncFileBuf), fp);
	memset(cmsFuncFileBuf, 0, sizeof(cmsFuncFileBuf));
	strcat(cmsFuncFileBuf, "#ifndef _STATS_FUNC_H\n");
	strcat(cmsFuncFileBuf, "#define _STATS_FUNC_H\n");
	fwrite(cmsFuncFileBuf, sizeof(char), strlen(cmsFuncFileBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*create cms task stats file.*/
	fp = fopen(STATUSFUNC_TABLE,"w+"); 
	if(fp == NULL){
		printf("fopen %s fail!\n\r", STATUSFUNC_TABLE);
		return -1;
	}
	sprintf(cmsFuncFileBuf, "/* Date:%s %s Auto Generated at building time, do not edit it. */\n\n", __DATE__, __TIME__);
	fwrite(cmsFuncFileBuf, sizeof(char), strlen(cmsFuncFileBuf), fp);
	memset(cmsFuncFileBuf, 0, sizeof(cmsFuncFileBuf));
	strcat(cmsFuncFileBuf, "#include <stdlib.h>\n");
	strcat(cmsFuncFileBuf, "#include \"cms_common.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"cmsXml_object.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"cms_objFunc.h\"\n");
	strcat(cmsFuncFileBuf, "#include \"cmsTask_statsFunc.h\"\n\n\n");
	strcat(cmsFuncFileBuf, "const cmsObjFunc_t stats_objFuncTable[]={\n");
	fwrite(cmsFuncFileBuf, sizeof(char), strlen(cmsFuncFileBuf), fp);      
	fclose(fp);
	fp = NULL;

	return 0;
}

static void cmsWriteRoutinetablefile(char *pre_str, char *file, char *objName, int OID, uint32_t priority){
	FILE *fp;
	char defbuf[1024];
	char tmpbuf[64];

	memset(defbuf, 0, sizeof(defbuf));
	memset(tmpbuf, 0, sizeof(tmpbuf));
	if(OID < 10)
		sprintf(tmpbuf,"/* %d */\t\t", OID);
	else
		sprintf(tmpbuf,"/* %d */\t", OID);

	strcat(defbuf, tmpbuf);
	strcat(defbuf, "{ ");

	if(strcmp(objName,"NULL")) strcat(defbuf, pre_str);

	strcat(defbuf, objName);

	if(priority == 2)
		sprintf(tmpbuf,", %s},\n", "CMS_NOTIFY_PRORITY_HIGHEST");
	else if (priority == 50)
		sprintf(tmpbuf,", %s},\n", "CMS_NOTIFY_PRORITY_MEDIAN");
	else if (priority == 99)
		sprintf(tmpbuf,", %s},\n", "CMS_NOTIFY_PRORITY_LOWEST");
	else
		sprintf(tmpbuf,", %u},\n", priority);

	strcat(defbuf, tmpbuf);
	fp = fopen(file,"a+"); 
	if(fp==NULL){
		printf("fopen %s fail!\n\r", file);
		return;
	}
	fwrite(defbuf, sizeof(char), strlen(defbuf), fp);      
	fclose(fp);

	return;
}

static void cmsWriteRoutinehfile(char *pre_str, char *file, char *objName){

	FILE *fp;
	char defbuf[2048];

	memset(defbuf, 0, sizeof(defbuf));
	strcat(defbuf, "int ");
	strcat(defbuf, pre_str);
	strcat(defbuf, objName);
	if(strcmp(pre_str,"stats_") == 0)
		strcat(defbuf, "(");
	else {
		strcat(defbuf, "( \\\n\t");
		strcat(defbuf, "const cmsObj_");
		strcat(defbuf, objName);
		strcat(defbuf, "_t");
		strcat(defbuf, " *oldObject, \\\n\t");
		strcat(defbuf, "const cmsObj_");
		strcat(defbuf, objName);
		strcat(defbuf, "_t");
		strcat(defbuf, " *newObject, \\\n\t");
	}

	strcat(defbuf, "const uint64_t IA);\n\n");
#if 0 
	//only for c file. (don't remove this!)
	strcat(defbuf, "const uint64_t IA)\n");
	strcat(defbuf, "{\n\treturn CMS_OK;\n}\n\n");
#endif
	fp = fopen(file,"a+"); 
	if(fp==NULL){
		printf("fopen %s fail!\n\r", file);
		return;
	}
	fwrite(defbuf, sizeof(char), strlen(defbuf), fp);      
	fclose(fp);
	return;
}
#if 0
static void cmsWriteRoutineCfile(char *pre_str, char *file, char *objName){

	FILE *fp;
	char defbuf[2048];
	size_t nmemb = 0;

	memset(defbuf, 0, sizeof(defbuf));
	strcat(defbuf, "int ");
	strcat(defbuf, pre_str);
	strcat(defbuf, objName);
	if(strcmp(pre_str,"status_") == 0)
		strcat(defbuf, "(");
	else {
		strcat(defbuf, "( \n\t");
		strcat(defbuf, "const cmsObj_");
		strcat(defbuf, objName);
		strcat(defbuf, "_t");
		strcat(defbuf, " *oldObject, \n\t");
		strcat(defbuf, "const cmsObj_");
		strcat(defbuf, objName);
		strcat(defbuf, "_t");
		strcat(defbuf, " *newObject, \n\t");
	}

	strcat(defbuf, "const uint64_t IA, \n\tconst uint32_t realId){\n\t");
	if((strcmp(pre_str,"status_") == 0) || (strcmp(pre_str,"be_") == 0)){
		strcat(defbuf, "return CMS_OK;\n}\n\n");
	}else if(strcmp(pre_str,"das_") == 0){
		strcat(defbuf, "return CMS_DB_TO_TASK;\n}\n\n");
	}

	fp = fopen(file,"a+"); 
	if(fp==NULL){
		printf("fopen %s fail!\n\r", file);
		return -1;
	}
	nmemb = fwrite(defbuf, sizeof(char), strlen(defbuf), fp);      
	fclose(fp);
}
#endif

#if 0
static void toWriteQueue(char *inputStr){
	char *delim = " {,}";
	char *p;
	struct functionList_s *node;
	char *Ptr=NULL;

	p =strtok_r(inputStr, delim, &Ptr);
	while((p = strtok_r(NULL, delim, &Ptr)))
	{
		if(strstr(p, "task_InternetGatewayDevice"))
		{
			node = malloc(sizeof(struct functionList_s));
			if(node == NULL) 
				return ;

			strcpy(node->functionName, p);

			p = strtok_r(NULL, delim, &Ptr);

			if(!strcmp(p, "CMS_NOTIFY_PRORITY_HIGHEST"))
				node->order = 2;
			else if(!strcmp(p, "CMS_NOTIFY_PRORITY_MEDIAN"))
				node->order = 50;
			else if(!strcmp(p, "CMS_NOTIFY_PRORITY_LOWEST"))
				node->order = 99;
			else
				node->order = atoi(p);

			LIST_ENQUEUE_BY_ORDER(functionQueue ,node);
			break;
		}
		
	}
	return;
}

static void cmsReOrderRoutinetable(char *filename){
	FILE *fp = NULL;
	char data[256] = {0};
   	char orderBuf[512] = {0};
	struct functionList_s *pCurFuncList = NULL;
  

	fp = fopen(filename,"a+");
	if(fp==NULL){
		printf("fopen %s fail!\n\r", filename);
		return;
	}
	
	while (fgets(data , 256, fp))
	{
		if(strstr(data, "task_InternetGatewayDevice"))
			toWriteQueue(data);
	}

	/*write to file*/
	pCurFuncList = functionQueue;

	memset(orderBuf, 0, sizeof(orderBuf));
	strcat(orderBuf, "\n\n\nconst cmsObjFunc_t bootupRoutinetable[]={\n");
	fwrite(orderBuf, sizeof(char), strlen(orderBuf), fp);      

	while(pCurFuncList) {
		memset(orderBuf, 0, sizeof(orderBuf));
		sprintf(orderBuf, "\t{%s, %d},\n", pCurFuncList->functionName, pCurFuncList->order);
		fwrite(orderBuf, sizeof(char), strlen(orderBuf), fp);      
		pCurFuncList = pCurFuncList->next;
	}

	memset(orderBuf, 0, sizeof(orderBuf));
	strcat(orderBuf, "\t{NULL, 0}\n");
	strcat(orderBuf, "};\n");
	fwrite(orderBuf, sizeof(char), strlen(orderBuf), fp);      
	fclose(fp);

	/*free WriteQueue*/
	pCurFuncList = functionQueue;
	while(pCurFuncList){
		functionQueue = functionQueue->next;
		free(pCurFuncList);
		pCurFuncList = functionQueue;
	}
	functionQueue = NULL;
	return;
}
#endif

static int cmsWriteObjMaxCountTable(void)
{
	FILE *fp = NULL;
	
	fp = fopen(INXCNT_HEADER,"w+"); 
	if(fp == NULL)
		return -1;
	
	strcat(OBJ_MAXCOUNT, OBJ_MAXCOUNT_TAIL);
	fwrite(OBJ_MAXCOUNT, sizeof(char), strlen(OBJ_MAXCOUNT), fp);
	fclose(fp);
	
	return 0;
}

static int loadXmlToShm(void)
{
	int ret=0;

	/*load sysdef.xml*/
	ret=cmsXml_loadRomToRam(xmlShmCb, SYS_DEF_XML_FILE);
	if ( ret != CMS_OK )
	{
		printf("cmsXml_loadRomToRam fail!\n\r");
		return -1;
	}
	printf( "sysdef total_size = %d\n", total_size );

	/* shm version + total shm size + used shm size + string offset. */
	xmlShmCb->rootNode = (objectNode_t *)( xmlShmCb->baseaddr + sizeof( uint32_t ) * 4 );
	if(!(xmlShmCb->rootNode)){
		printf("sysdef.xml root node is null\n\r");
		return 0;
	}

	/*load predef.xml*/
	ret=cmsXml_loadPredefSettingToRam(xmlShmCb, PRE_DEF_XML_FILE);
	if ( ret != CMS_OK )
	{
		printf("cmsXml_loadPredefSettingToRam fail!\n\r");
		return -1;
	}

	return 0;
}

static int cmsFinHeaderFile(void)
{
	FILE *fp = NULL;
	char headerEndBuf[BUFLEN_256] = {0};

	/*add end define obj.h*/
	strcat(headerEndBuf, "#endif\n");
	fp = fopen(OBJ_HEADER,"a+"); 
	if ( fp == NULL )
	{
		printf("fopen cmsXml_object.h fail!\n\r");
		return -1;
	}
	fwrite(headerEndBuf, sizeof(char), strlen(headerEndBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*add end define obj_id.h*/
	memset(headerEndBuf, 0, sizeof(headerEndBuf));
	sprintf( headerEndBuf, "\n#define MAXOIDNUMBER %d\n\n", --totalOIDNumber );
	strcat(headerEndBuf, "#endif\n");
	fp = fopen(OBJID_HEADER,"a+"); 
	if ( fp == NULL )
	{
		printf("fopen rdm_obj_id.h fail!\n\r");
		return -1;
	}
	fwrite(headerEndBuf, sizeof(char), strlen(headerEndBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*add end define obj_table.h*/
	fp = fopen(OBJIDTABLE_HEADER,"a+"); 
	if ( fp == NULL )
	{
		printf("fopen rdm_oid_table.h fail!\n\r");
		return -1;
	}
	fwrite( OBJID_FILE_TAIL, sizeof( char ), strlen( OBJID_FILE_TAIL ), fp );
	memset(headerEndBuf, 0, sizeof(headerEndBuf));
	strcat(headerEndBuf, "#endif\n");
	fwrite(headerEndBuf, sizeof(char), strlen(headerEndBuf), fp);    
	fclose(fp);
	fp = NULL;

	return 0;
}

static int generateCmsHeaderFile(void)
{
	FILE *fp = NULL;
	char headerFileBuf[BUFLEN_256] = {0};
	
	/*
	*generate three header file include definition
	*/
	/*first header file*/
	strcat(headerFileBuf, "#ifndef _CMSXML_OBJECT_H\n");
	strcat(headerFileBuf, "#define _CMSXML_OBJECT_H\n");
	strcat(headerFileBuf, "#include <stdint.h>\n");
	fp = fopen(OBJ_HEADER,"w+"); 
	if ( fp == NULL )
	{
		CMS_LOG(LL_ERROR, "fopen %s fail!", OBJID_HEADER);
		return -1;
	}
	fwrite(headerFileBuf, sizeof(char), strlen(headerFileBuf), fp);      
	fclose(fp);
	fp = NULL;

	/*second header file*/
	memset(headerFileBuf, 0, sizeof(headerFileBuf));
	strcat(headerFileBuf, "#ifndef _CMSXML_OBJ_ID_H\n");
	strcat(headerFileBuf, "#define _CMSXML_OBJ_ID_H\n");
	fp = fopen(OBJID_HEADER,"w+"); 
	if ( fp == NULL )
	{
		printf("fopen cmsXml_obj_id.h fail!\n\r");
		return -1;
	}
	fwrite(headerFileBuf, sizeof(char), strlen(headerFileBuf), fp);      
	fwrite( OBJID_FILE_HEADER, sizeof( char ), strlen( OBJID_FILE_HEADER ), fp );
	fclose(fp);
	fp = NULL;

	/*third header file*/
	memset(headerFileBuf, 0, sizeof(headerFileBuf));
	strcat(headerFileBuf, "#ifndef _CMSXML_OBJ_TABLE_H\n");
	strcat(headerFileBuf, "#define _CMSXML_OBJ_TABLE_H\n");
	fp = fopen(OBJIDTABLE_HEADER,"w+"); 
	if ( fp == NULL )
	{
		printf("fopen cmsXml_oid_table.h fail!\n\r");
		return -1;
	}
	fwrite(headerFileBuf, sizeof(char), strlen(headerFileBuf), fp);  
	fwrite( OBJID_TABLE_HEADER, sizeof( char ), strlen( OBJID_TABLE_HEADER ), fp );
	fclose(fp);
	fp = NULL;

	return 0;
}

static int cmsXml_defaultConfg_enc(void)
{	
	char cmdStr[1024] = {0};
	DIR *preConfDir = NULL;
	struct dirent *dirPtr = NULL;
	char preConfIn[320] = {0};
	char preConfOut[512] = {0};
	int count = 0;

	sprintf(cmdStr, "openssl aes-128-cbc -e -in %s -out %s -K %s -iv %s", CUS_DEF_XML, CUS_DEF_ENC,  CMS_XML_KEY, CMS_XML_IV);

    CMS_LOG(LL_PRINT, "cmd:%s", cmdStr);
	if(system(cmdStr)){
        CMS_LOG(LL_ERROR, "do cmd [%s] failed!", cmdStr);
    }

	if( access(CUS_DEF_ENC, F_OK) == -1){
		printf("enc default xml fail!!!");
		return CMS_NOK;
	}

	printf("enc default xml success!\n");

	preConfDir = opendir(PRE_CONFIG_PATH);
	if(preConfDir != NULL){
		while((dirPtr = readdir(preConfDir)) != NULL){
			if(strcmp(dirPtr->d_name, ".") == 0 || strcmp(dirPtr->d_name, "..") == 0 || strstr(dirPtr->d_name, ".enc") != NULL)
				continue;

			memset(preConfIn, 0, 320);
			memset(preConfOut, 0, 512);
			memset(cmdStr, 0, 1024);
			
			sprintf(preConfIn, "%s%s", PRE_CONFIG_PATH, dirPtr->d_name);
			strncpy(preConfOut, preConfIn, strlen(preConfIn)-3);
			strcat(preConfOut, "enc");
			//printf("before enc preConf dir file %s, after enc %s\n", preConfIn, preConfOut);
			
			
			sprintf(cmdStr, "openssl aes-128-cbc -e -in %s -out %s -K %s -iv %s", preConfIn, preConfOut, CMS_XML_KEY, CMS_XML_IV);
	        if(system(cmdStr)){
                CMS_LOG(LL_ERROR, "do cmd [%s] failed!", cmdStr);
            }

			if( access(preConfOut, F_OK) == -1){
				printf("enc preConf xml %s fail!!!", preConfOut);
				return CMS_NOK;
			}
			count++;
		}
		closedir(preConfDir);

		if(count == 0){
			memset(cmdStr, 0, 256);
			sprintf(cmdStr, "cp %s %s", CUS_DEF_ENC, PRE_CONFIG_PATH);
	        if(system(cmdStr)){
                CMS_LOG(LL_ERROR, "do cmd [%s] failed!", cmdStr);
            }
		}
	}

	return CMS_OK;
}

/*
	Description: 
		1. create xml share memory file config.default.cms.
		2. create header file for apps which use cms.
	Parameters:
		none		
	return:
		return CMS_OK
*/
int main(void)
{
	void *mPtr = NULL;			//data module memory ptr
	uint32_t mVersion = 0;		//data module version
	uint32_t msize = 0;			//data module size
	int ret = CMS_NOK;
	/*add for check and enc pre config file*/
	DIR *preConfDir = NULL;
	struct dirent *dirPtr = NULL;
	char preConfPath[512] = {0};

	CMS_LOG(LL_INFO, "xml parse to share memory process");
	
	/*create cms object header file*/
	if(generateCmsHeaderFile() == -1){
		CMS_LOG(LL_ERROR, "create cms obj header file fail.");
		return CMS_NOK;
	}

	/*create cms func file*/
	if(cmsInitRoutinehfile() == -1){
		CMS_LOG(LL_ERROR, "create cms func file fail.");
		return CMS_NOK;
	}

	/*load sysdef & predef and generate config.default.cms
	*allocate memory for xml, sfu 1M, hgu 3M.
	*xml shm header include version, size, used size and string offset.
	*/
	current_offset += sizeof( uint32_t ) * 4;	/* version, size, used size and string offset. */
	total_size += sizeof( uint32_t ) * 4;		/* version, size, used size and string offset. */
	mPtr = calloc( X2S_MEMORY_SIZE, 1 );
	memset(mPtr, 0, X2S_MEMORY_SIZE);
	memset(xmlShmCb, 0, sizeof(cmsXmlCb_t));
	xmlShmCb->baseaddr = mPtr;
	
	/*load xml to shm*/
	if(loadXmlToShm() == -1){
		CMS_LOG(LL_ERROR, "load sysdef & predef xml to shm fail.");
		free(mPtr);
		return CMS_NOK;
	}
	
	/*init shm header 4 bytes*/
	mVersion = HTONL(CMS_FILE_VERSION);
	memcpy(mPtr, &mVersion, sizeof(uint32_t));
	msize = HTONL( X2S_MEMORY_SIZE );
	memcpy( mPtr + sizeof( uint32_t ), &msize, sizeof( uint32_t ) ); /*shm size*/
	msize = HTONL( X2S_MEMORY_SIZE - 1 );
	memcpy( mPtr + sizeof( uint32_t ) * 3, &msize, sizeof( uint32_t ) ); /*string offset*/
	msize = HTONL(total_size);
	memcpy( mPtr + sizeof( uint32_t ) * 2, &msize, sizeof( uint32_t ) ); /*used shm size*/
	xmlShmCb->shmSize = X2S_MEMORY_SIZE;
	CMS_LOG(LL_INFO, "xml shm total size %d, used size %d", xmlShmCb->shmSize, total_size);

	/*save shm to cms file*/
	ret = cms_genCmsFile(xmlShmCb, NULL, PRE_DEF_SHM);
	if(ret == CMS_NOK){
		CMS_LOG(LL_ERROR, "generate file %s fail.", PRE_DEF_SHM);
		free(mPtr);
		return CMS_NOK;
	}else{
        CMS_LOG(LL_INFO, "generate file %s success", PRE_DEF_SHM);
    }

	/*check config.default.xml*/
	if (cmsXml_checkXml(xmlShmCb, CUS_DEF_XML) == CMS_NOK)
	{
		CMS_LOG(LL_ERROR, "cms check default xml,  result is fail!");
		free(mPtr);
		return CMS_NOK;
	}
	/*check pre config xml file*/
	preConfDir = opendir(PRE_CONFIG_PATH);
	if(preConfDir != NULL){
		while((dirPtr = readdir(preConfDir)) != NULL){
			if(strcmp(dirPtr->d_name, ".") == 0 || strcmp(dirPtr->d_name, "..") == 0 ||  strstr(dirPtr->d_name, ".enc") != NULL)
				continue;
			memset(preConfPath, 0, 512);
			sprintf(preConfPath, "%s%s", PRE_CONFIG_PATH, dirPtr->d_name);
			printf("preConf dir file %s\n", preConfPath);
			
			if (cmsXml_checkXml(xmlShmCb, preConfPath) == CMS_NOK)
			{
				CMS_LOG(LL_ERROR, "cms check %s,  result is fail!", dirPtr->d_name);
				free(mPtr);
				return CMS_NOK;
			}
		}
		closedir(preConfDir);
	}
	free(mPtr);
	
	/*add header include end definition*/
	if(cmsFinHeaderFile() == -1){
		CMS_LOG(LL_ERROR, "add cms header end fail.");
		return CMS_NOK;
	}

	/*add cms header end define*/
	if(cmsFinRoutinehfile() == -1){
		CMS_LOG(LL_ERROR, "add cms header end fail.");
		return CMS_NOK;
	}
	
#if 0
	cmsReOrderRoutinetable(TASKFUNC_TABLE);
#endif
	cmsWriteObjMaxCountTable();

	if(cmsXml_defaultConfg_enc() == CMS_NOK)
		return CMS_NOK;
	
	return CMS_OK;
}

